/*
 * Copyright 2009-2010 the original author or authors.
 *
 * Licensed under the Apache license, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.internna.iwebjtracker.boot.tasks.jobs;

import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.internna.iwebmvc.dao.DAO;
import org.internna.iwebmvc.model.UUID;
import org.internna.iwebmvc.utils.Assert;
import org.internna.iwebmvc.utils.CollectionUtils;
import org.internna.iwebjtracker.model.DefaultProject;
import org.internna.iwebjtracker.issue.model.Issue.Status;
import org.internna.iwebjtracker.model.statistics.OpenClosed;

/**
 * Aggregates information of open and closed issues in every project at a given date.
 *
 * @author Jose Noheda
 * @since 1.0
 */
public final class OpenClosedCollector {

    private final DAO dao;

    /**
     * Ensures a DAO is configured.
     *
     * @param dao a non null instance
     */
    public OpenClosedCollector(DAO dao) {
        Assert.notNull(dao);
        this.dao = dao;
    }

    /**
     * Retrieves the collection of projects and generates reporting data for the 
     * day of execution.
     */
    @SuppressWarnings("unchecked")
    public void collect() {
        dao.executeUpdate("DELETE FROM OpenClosed WHERE date >= current_date()");
        List<Object[]> data = collectLastModifiedData();
        if (CollectionUtils.isNotEmpty(data)) {
            OpenClosed openClosed = new OpenClosed();
            for (Object[] row : data) {
                UUID id = new UUID((byte[]) row[0]);
                if ((openClosed.getProject() != null) && !id.equals(openClosed.getProject().getId())) {
                    dao.create(openClosed);
                    openClosed = new OpenClosed();
                }
                openClosed.setProject(dao.find(DefaultProject.class, id));
                if (Status.CLOSED.ordinal() == (Integer) row[1]) {
                    openClosed.setClosed(Integer.parseInt(row[2].toString()));
                } else {
                    openClosed.addOpen(Integer.parseInt(row[2].toString()));
                }
            }
            dao.create(openClosed);
        }
    }

    @SuppressWarnings("unchecked")
    private List<Object[]> collectLastModifiedData() {
        Calendar calendar = Calendar.getInstance(Locale.ENGLISH);
        Map<String, Object> params = new HashMap<String, Object>(1);
        calendar.add(Calendar.MONTH, -1);
        params.put("lastMonth", calendar.getTime());
        return (List) dao.executeNativeQuery("SELECT PROJECT, STATUS, COUNT(*) FROM ISSUES WHERE LASTMODIFIED >= :lastMonth GROUP BY PROJECT, STATUS ORDER BY PROJECT", 0, 99999, params);
    }

}
